/*
 * Copyright (c) 2007, 2008 Johannes Krampf <Johannes.Krampf@htw-dresden.de>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#define CRC32POLY 0xEDB88320 /* umgekehrtes Standardpolynom */

#include <stdio.h>
#include <stdlib.h>

#include "general.h"
#include "bstring/bstrlib.h"

int MinLen(int len1, int len2) {
	return (len1<len2) ? len1 : len2;
}

/*
 * CRC32-Implementierung nach
 * http://www.ross.net/crc/download/crc_v3.txt und
 * http://de.wikipedia.org/wiki/Zyklische_Redundanzprüfung
 */
unsigned int CRC32(unsigned char *buffer, int length) {
   int i, j;
   unsigned int crc = 0xFFFFFFFF;
   
   for (i=0;i<length;i++) {
      crc ^= buffer[i];
      for (j=0;j<8;j++) {
          crc = (crc >> 1) ^ (CRC32POLY & -(0x01 & crc));
      }
   }
   return ~crc;
}


bstring BinToHex(int length, unsigned char* data) {
	int i;
	bstring hexdata = cstr2bstr("");
	const char hexval[16] = "0123456789ABCDEF";
	
	if (NULL == hexdata) {
		MemError();
		return NULL;
	}
	
	for (i=0;i<length;i++) {
		bconchar(hexdata, hexval[data[i] >> 4]);
		bconchar(hexdata, hexval[data[i] & 0x0F]);
	}
	
	return hexdata;
}

int HexCharToInt(char hexchar) {
	switch(hexchar) {
		case '0': return 0;
		case '1': return 1;
		case '2': return 2;
		case '3': return 3;
		case '4': return 4;
		case '5': return 5;
		case '6': return 6;
		case '7': return 7;
		case '8': return 8;
		case '9': return 9;
		case 'a':
		case 'A': return 10;
		case 'b':
		case 'B': return 11;
		case 'c':
		case 'C': return 12;
		case 'd':
		case 'D': return 13;
		case 'e':
		case 'E': return 14;
		case 'f':
		case 'F': return 15;
	}
	fprintf(stderr, "HexCharToInt: Ungueltiger Charakter %c\n", hexchar);
	return -1;
}

unsigned int HexStringToUInt(char* hexstring) {
	int i, j = 1;
	unsigned int result = 0;
	
	for (i=7;i>=0;i--) {
		result += j*HexCharToInt(hexstring[i]);
		j *= 16;
	}
	return result;
}

bstring HexToBin(char* hexdata) {
	int i;
	int length;
	bstring bindata = cstr2bstr("");

	length = (strlen(hexdata)/2);

	for (i=0;i<length;i++) {
		bconchar(bindata, (HexCharToInt(hexdata[2*i]) << 4) + HexCharToInt(hexdata[2*i+1]));
	}
	
	return bindata;
}

void MemError() {
	fprintf(stderr, "Speicherfehler!\n");
}

